{
 "cells": [
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-01-10T11:11:21.928599Z",
     "start_time": "2025-01-10T11:11:21.235228Z"
    }
   },
   "source": [
    "# 导入库\n",
    "import time\n",
    "\n",
    "from sklearn.datasets import load_iris, fetch_20newsgroups, fetch_california_housing\n",
    "from sklearn.model_selection import train_test_split, GridSearchCV\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.feature_extraction.text import TfidfVectorizer\n",
    "from sklearn.naive_bayes import MultinomialNB\n",
    "from sklearn.metrics import classification_report\n",
    "from sklearn.feature_extraction import DictVectorizer\n",
    "from sklearn.tree import DecisionTreeClassifier, export_graphviz\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.metrics import roc_auc_score"
   ],
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 分类估计器",
   "id": "d8020afc90a25c61"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:11:39.004909Z",
     "start_time": "2025-01-10T11:11:32.230718Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# K近邻\n",
    "\"\"\"\n",
    "K-近邻预测用户签到位置\n",
    ":return:None\n",
    "\"\"\"\n",
    "# 读取数据\n",
    "data = pd.read_csv(\"./data/FBlocation/train.csv\")\n",
    "\n",
    "print(data.head(10))\n",
    "print(data.shape)\n",
    "print(data.info())\n",
    "# 处理数据\n",
    "# .qurey()方法可以对数据进行筛选，只保留满足条件的数据\n",
    "data = data.query(\"x > 1.0 &  x < 1.25 & y > 2.5 & y < 2.75\")"
   ],
   "id": "be1a70cdeb7ca8b1",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   row_id       x       y  accuracy    time    place_id\n",
      "0       0  0.7941  9.0809        54  470702  8523065625\n",
      "1       1  5.9567  4.7968        13  186555  1757726713\n",
      "2       2  8.3078  7.0407        74  322648  1137537235\n",
      "3       3  7.3665  2.5165        65  704587  6567393236\n",
      "4       4  4.0961  1.1307        31  472130  7440663949\n",
      "5       5  3.8099  1.9586        75  178065  6289802927\n",
      "6       6  6.3336  4.3720        13  666829  9931249544\n",
      "7       7  5.7409  6.7697        85  369002  5662813655\n",
      "8       8  4.3114  6.9410         3  166384  8471780938\n",
      "9       9  6.3414  0.0758        65  400060  1253803156\n",
      "(29118021, 6)\n",
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 29118021 entries, 0 to 29118020\n",
      "Data columns (total 6 columns):\n",
      " #   Column    Dtype  \n",
      "---  ------    -----  \n",
      " 0   row_id    int64  \n",
      " 1   x         float64\n",
      " 2   y         float64\n",
      " 3   accuracy  int64  \n",
      " 4   time      int64  \n",
      " 5   place_id  int64  \n",
      "dtypes: float64(2), int64(4)\n",
      "memory usage: 1.3 GB\n",
      "None\n"
     ]
    }
   ],
   "execution_count": 3
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:11:41.224172Z",
     "start_time": "2025-01-10T11:11:41.213197Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 查看有无缺失值\n",
    "print(\"数据形状：\\n\", data.shape)\n",
    "print(\"数据描述：\\n\", data.describe())\n",
    "print(\"数据缺失值：\\n\", data.isnull().sum())"
   ],
   "id": "2e68272840034589",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数据形状：\n",
      " (17710, 6)\n",
      "数据描述：\n",
      "              row_id             x             y      accuracy           time  \\\n",
      "count  1.771000e+04  17710.000000  17710.000000  17710.000000   17710.000000   \n",
      "mean   1.450569e+07      1.122538      2.632309     82.482101  397551.263128   \n",
      "std    8.353805e+06      0.077086      0.070144    113.613227  234601.097883   \n",
      "min    6.000000e+02      1.000100      2.500100      1.000000     119.000000   \n",
      "25%    7.327816e+06      1.049200      2.573800     25.000000  174069.750000   \n",
      "50%    1.443071e+07      1.123300      2.642300     62.000000  403387.500000   \n",
      "75%    2.163463e+07      1.190500      2.687800     75.000000  602111.750000   \n",
      "max    2.911215e+07      1.249900      2.749900   1004.000000  786218.000000   \n",
      "\n",
      "           place_id  \n",
      "count  1.771000e+04  \n",
      "mean   5.129895e+09  \n",
      "std    2.357399e+09  \n",
      "min    1.012024e+09  \n",
      "25%    3.312464e+09  \n",
      "50%    5.261906e+09  \n",
      "75%    6.766325e+09  \n",
      "max    9.980711e+09  \n",
      "数据缺失值：\n",
      " row_id      0\n",
      "x           0\n",
      "y           0\n",
      "accuracy    0\n",
      "time        0\n",
      "place_id    0\n",
      "dtype: int64\n"
     ]
    }
   ],
   "execution_count": 4
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:11:43.859998Z",
     "start_time": "2025-01-10T11:11:43.854535Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# to_datetime()方法可以把时间格式转换成日期格式,unit是秒，把秒转换成日期格式\n",
    "# 处理时间的数据，unit是秒，把秒转换成日期格式\n",
    "time_value = pd.to_datetime(data['time'], unit='s')\n",
    "\n",
    "print(\"时间格式转化为日期格式：\\n\", time_value[0:10])  #最大时间是1月10号\n",
    "\n",
    "# 把日期格式转换成 字典格式，把年，月，日，时，分，秒转换为字典格式，\n",
    "# DatatimeIndex()方法可以把日期格式转换成日期索引格式\n",
    "time_value = pd.DatetimeIndex(time_value)\n",
    "print(\"日期格式转化为日期索引格式：\\n\", time_value[0:10])"
   ],
   "id": "be1aba7ac494ff3",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "时间格式转化为日期格式：\n",
      " 600    1970-01-01 18:09:40\n",
      "957    1970-01-10 02:11:10\n",
      "4345   1970-01-05 15:08:02\n",
      "4735   1970-01-06 23:03:03\n",
      "5580   1970-01-09 11:26:50\n",
      "6090   1970-01-02 16:25:07\n",
      "6234   1970-01-04 15:52:57\n",
      "6350   1970-01-01 10:13:36\n",
      "7468   1970-01-09 15:26:06\n",
      "8478   1970-01-08 23:52:02\n",
      "Name: time, dtype: datetime64[ns]\n",
      "日期格式转化为日期索引格式：\n",
      " DatetimeIndex(['1970-01-01 18:09:40', '1970-01-10 02:11:10',\n",
      "               '1970-01-05 15:08:02', '1970-01-06 23:03:03',\n",
      "               '1970-01-09 11:26:50', '1970-01-02 16:25:07',\n",
      "               '1970-01-04 15:52:57', '1970-01-01 10:13:36',\n",
      "               '1970-01-09 15:26:06', '1970-01-08 23:52:02'],\n",
      "              dtype='datetime64[ns]', name='time', freq=None)\n"
     ]
    }
   ],
   "execution_count": 5
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:11:44.514049Z",
     "start_time": "2025-01-10T11:11:44.504105Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 构造一些特征，执行的警告是因为操作是复制，loc是直接放入\n",
    "# data['day'] = time_value.day\n",
    "# data['hour'] = time_value.hour\n",
    "# data['weekday'] = time_value.weekday\n",
    "\n",
    "# 日期，是否是周末\n",
    "# 小时对于个人行为的影响较大\n",
    "\n",
    "# 等价上面插入的方式\n",
    "# .insert()方法可以插入数据，axis=1代表插入到最后一列\n",
    "\n",
    "#data.shape[1]是代表插入到最后的意思,一个月的哪一天\n",
    "# .day属性代表日期，.hour属性代表小时，.weekday属性代表星期几\n",
    "data.insert(data.shape[1], 'day', time_value.day)\n",
    "\n",
    "#是否去一个地方打卡，早上，中午，晚上是有影响的\n",
    "data.insert(data.shape[1], 'hour', time_value.hour)\n",
    "\n",
    "#0代表周一，6代表周日，星期几\n",
    "data.insert(data.shape[1], 'weekday', time_value.weekday)\n",
    "\n",
    "# 把时间戳特征删除\n",
    "data = data.drop(['time'], axis=1)\n",
    "data.head()"
   ],
   "id": "5800e8bc254ced20",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "      row_id       x       y  accuracy    place_id  day  hour  weekday\n",
       "600      600  1.2214  2.7023        17  6683426742    1    18        3\n",
       "957      957  1.1832  2.6891        58  6683426742   10     2        5\n",
       "4345    4345  1.1935  2.6550        11  6889790653    5    15        0\n",
       "4735    4735  1.1452  2.6074        49  6822359752    6    23        1\n",
       "5580    5580  1.0089  2.7287        19  1527921905    9    11        4"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>row_id</th>\n",
       "      <th>x</th>\n",
       "      <th>y</th>\n",
       "      <th>accuracy</th>\n",
       "      <th>place_id</th>\n",
       "      <th>day</th>\n",
       "      <th>hour</th>\n",
       "      <th>weekday</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>600</th>\n",
       "      <td>600</td>\n",
       "      <td>1.2214</td>\n",
       "      <td>2.7023</td>\n",
       "      <td>17</td>\n",
       "      <td>6683426742</td>\n",
       "      <td>1</td>\n",
       "      <td>18</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>957</th>\n",
       "      <td>957</td>\n",
       "      <td>1.1832</td>\n",
       "      <td>2.6891</td>\n",
       "      <td>58</td>\n",
       "      <td>6683426742</td>\n",
       "      <td>10</td>\n",
       "      <td>2</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4345</th>\n",
       "      <td>4345</td>\n",
       "      <td>1.1935</td>\n",
       "      <td>2.6550</td>\n",
       "      <td>11</td>\n",
       "      <td>6889790653</td>\n",
       "      <td>5</td>\n",
       "      <td>15</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4735</th>\n",
       "      <td>4735</td>\n",
       "      <td>1.1452</td>\n",
       "      <td>2.6074</td>\n",
       "      <td>49</td>\n",
       "      <td>6822359752</td>\n",
       "      <td>6</td>\n",
       "      <td>23</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5580</th>\n",
       "      <td>5580</td>\n",
       "      <td>1.0089</td>\n",
       "      <td>2.7287</td>\n",
       "      <td>19</td>\n",
       "      <td>1527921905</td>\n",
       "      <td>9</td>\n",
       "      <td>11</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 6
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:11:45.126635Z",
     "start_time": "2025-01-10T11:11:45.119128Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# # 把签到数量少于n个目标位置删除，place_id是标签，即目标值\n",
    "place_count = data.groupby('place_id').count()\n",
    "\n",
    "#打卡地点总计805个，50%打卡小于2次\n",
    "print(\"打卡地点总计：\\n\", place_count['x'].describe())\n",
    "\n",
    "# 把index变为0,1,2，3,4,5,6这种效果，从零开始排，原来的index是row_id\n",
    "#只选择去的人大于3的数据，认为1,2,3的是噪音，这个地方去的人很少，不用推荐给其他人\n",
    "tf = place_count[place_count.row_id > 3].reset_index()\n",
    "\n",
    "#剩余的签到地点\n",
    "print(\"剩余的签到地点：\\n\", tf.shape)\n",
    "\n",
    "#isin可以过滤某一列要在一组值\n",
    "data = data[data['place_id'].isin(tf.place_id)]\n",
    "\n",
    "# # 取出数据当中的特征值和目标值\n",
    "y = data['place_id']\n",
    "\n",
    "# 删除目标值，保留特征值，\n",
    "x = data.drop(['place_id'], axis=1)\n",
    "\n",
    "# 删除无用的特征值，row_id是索引,这就是噪音\n",
    "x = x.drop(['row_id'], axis=1)"
   ],
   "id": "2d078cc066750f36",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "打卡地点总计：\n",
      " count     805.000000\n",
      "mean       22.000000\n",
      "std        88.955632\n",
      "min         1.000000\n",
      "25%         1.000000\n",
      "50%         2.000000\n",
      "75%         5.000000\n",
      "max      1044.000000\n",
      "Name: x, dtype: float64\n",
      "剩余的签到地点：\n",
      " (239, 8)\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:11:45.639806Z",
     "start_time": "2025-01-10T11:11:45.633046Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 进行数据的分割训练集合测试集\n",
    "x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25, random_state=1)\n",
    "\n",
    "# 特征工程（标准化）\n",
    "std = StandardScaler()\n",
    "\n",
    "# 对测试集和训练集的特征值进行标准化,服务于knn fit\n",
    "x_train = std.fit_transform(x_train)\n",
    "\n",
    "#transform返回的是copy，不在原有的输入对象中去修改\n",
    "#transfrom不再进行均值和方差的计算，是在原有的基础上去标准化\n",
    "x_test = std.transform(x_test)"
   ],
   "id": "dd85788f23da2bb5",
   "outputs": [],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:11:46.332496Z",
     "start_time": "2025-01-10T11:11:46.167072Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 进行算法流程 \n",
    "# 超参数，可以通过设置n_neighbors=5，来调整结果好坏\n",
    "knn = KNeighborsClassifier(n_neighbors=3)\n",
    "\n",
    "# fit:训练模型\n",
    "# predict:预测模型,score:评估模型，\n",
    "# 训练，knn的fit是不训练的，只是把训练集的特征值和目标值放入到内存中\n",
    "knn.fit(x_train, y_train)\n",
    "\n",
    "# 得出预测结果\n",
    "y_predict = knn.predict(x_test)\n",
    "\n",
    "print(\"预测的目标签到位置为：\", y_predict[0:10])\n",
    "\n",
    "# # 得出准确率,是评估指标\n",
    "print(\"预测的准确率:\", knn.score(x_test, y_test))\n",
    "print(y_predict)"
   ],
   "id": "15f31784f455441c",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预测的目标签到位置为： [5689129232 1097200869 6097504486 9632980559 6424972551 1097200869\n",
      " 3952821602 3533177779 1435128522 3312463746]\n",
      "预测的准确率: 0.46430260047281324\n",
      "[5689129232 1097200869 6097504486 ... 7803770431 6424972551 4492549925]\n"
     ]
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 调超参：网格搜索",
   "id": "a9b4733499f57c53"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:11:50.407370Z",
     "start_time": "2025-01-10T11:11:48.142325Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 构造一些参数（超参）的值进行搜索\n",
    "param = {\"n_neighbors\": [3, 5, 10, 12, 15], 'weights': ['uniform', 'distance']}\n",
    "#\n",
    "# 进行网格搜索，cv=3是3折交叉验证，用其中2折训练，1折验证\n",
    "gc = GridSearchCV(knn, param_grid=param, cv=3)\n",
    "\n",
    "#你给它的x_train，它又分为训练集，验证集\n",
    "gc.fit(x_train, y_train)\n",
    "\n",
    "# 预测准确率\n",
    "print(\"在测试集上准确率：\", gc.score(x_test, y_test))\n",
    "\n",
    "#最好的结果\n",
    "print(\"在交叉验证当中最好的结果：\", gc.best_score_)\n",
    "\n",
    "#最好的模型,告诉你用了哪些参数\n",
    "print(\"选择最好的模型是：\", gc.best_estimator_)\n",
    "\n",
    "print(\"每个超参数每次交叉验证的结果：\")\n",
    "gc.cv_results_"
   ],
   "id": "32a223223cefe466",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\35493\\AppData\\Roaming\\Python\\Python312\\site-packages\\sklearn\\model_selection\\_split.py:805: UserWarning: The least populated class in y has only 1 members, which is less than n_splits=3.\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "在测试集上准确率： 0.49763593380614657\n",
      "在交叉验证当中最好的结果： 0.4816362349278435\n",
      "选择最好的模型是： KNeighborsClassifier(n_neighbors=12, weights='distance')\n",
      "每个超参数每次交叉验证的结果：\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'mean_fit_time': array([0.00567635, 0.00572252, 0.00521231, 0.00499153, 0.00550493,\n",
       "        0.00784135, 0.00668128, 0.00501402, 0.00506449, 0.00511257]),\n",
       " 'std_fit_time': array([2.41063573e-04, 2.09764183e-04, 3.19539961e-04, 5.86160792e-04,\n",
       "        4.04033438e-04, 1.24891332e-03, 2.00784568e-03, 4.04359847e-04,\n",
       "        4.50684694e-05, 1.06201019e-04]),\n",
       " 'mean_score_time': array([0.0674324 , 0.03104488, 0.06798514, 0.03855427, 0.10043494,\n",
       "        0.07793601, 0.09014765, 0.05135099, 0.08773979, 0.05833809]),\n",
       " 'std_score_time': array([2.88157536e-03, 2.96376596e-04, 5.52604768e-04, 7.75372649e-03,\n",
       "        1.85444774e-02, 5.58695108e-03, 1.20521462e-02, 8.56752076e-05,\n",
       "        3.64076103e-03, 1.40411622e-03]),\n",
       " 'param_n_neighbors': masked_array(data=[3, 3, 5, 5, 10, 10, 12, 12, 15, 15],\n",
       "              mask=[False, False, False, False, False, False, False, False,\n",
       "                    False, False],\n",
       "        fill_value=999999),\n",
       " 'param_weights': masked_array(data=['uniform', 'distance', 'uniform', 'distance',\n",
       "                    'uniform', 'distance', 'uniform', 'distance',\n",
       "                    'uniform', 'distance'],\n",
       "              mask=[False, False, False, False, False, False, False, False,\n",
       "                    False, False],\n",
       "        fill_value=np.str_('?'),\n",
       "             dtype=object),\n",
       " 'params': [{'n_neighbors': 3, 'weights': 'uniform'},\n",
       "  {'n_neighbors': 3, 'weights': 'distance'},\n",
       "  {'n_neighbors': 5, 'weights': 'uniform'},\n",
       "  {'n_neighbors': 5, 'weights': 'distance'},\n",
       "  {'n_neighbors': 10, 'weights': 'uniform'},\n",
       "  {'n_neighbors': 10, 'weights': 'distance'},\n",
       "  {'n_neighbors': 12, 'weights': 'uniform'},\n",
       "  {'n_neighbors': 12, 'weights': 'distance'},\n",
       "  {'n_neighbors': 15, 'weights': 'uniform'},\n",
       "  {'n_neighbors': 15, 'weights': 'distance'}],\n",
       " 'split0_test_score': array([0.44468085, 0.4534279 , 0.4607565 , 0.47399527, 0.46170213,\n",
       "        0.48014184, 0.45650118, 0.48108747, 0.45508274, 0.47895981]),\n",
       " 'split1_test_score': array([0.43390873, 0.4542445 , 0.45660913, 0.47528967, 0.45542681,\n",
       "        0.48238354, 0.45329865, 0.48049184, 0.44809648, 0.47623552]),\n",
       " 'split2_test_score': array([0.43982029, 0.4561362 , 0.45684559, 0.47221565, 0.4618113 ,\n",
       "        0.48191062, 0.45897375, 0.48332939, 0.46062899, 0.48049184]),\n",
       " 'mean_test_score': array([0.43946996, 0.45460287, 0.45807041, 0.47383353, 0.45964675,\n",
       "        0.48147867, 0.45625786, 0.48163623, 0.45460274, 0.47856239]),\n",
       " 'std_test_score': array([0.00440467, 0.00113433, 0.00190181, 0.00126016, 0.00298428,\n",
       "        0.00096479, 0.00232323, 0.00122169, 0.00512762, 0.00176021]),\n",
       " 'rank_test_score': array([10,  8,  6,  4,  5,  2,  7,  1,  9,  3], dtype=int32)}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 10
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 朴素贝叶斯",
   "id": "55f8fc378457677b"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:14:50.956923Z",
     "start_time": "2025-01-10T11:14:50.791504Z"
    }
   },
   "cell_type": "code",
   "source": [
    "\"\"\"\n",
    "朴素贝叶斯进行文本分类\n",
    ":return: None\n",
    "\"\"\"\n",
    "news = fetch_20newsgroups(subset='all', data_home='data')\n",
    "\n",
    "#样本数，包含的特征\n",
    "print(len(news.data))\n",
    "\n",
    "#第一个样本 特征\n",
    "print(news.data[0])\n",
    "\n",
    "#标签\n",
    "print(news.target[0:5])\n",
    "\n",
    "#标签的类别\n",
    "print(np.unique(news.target))\n",
    "\n",
    "#标签的名字\n",
    "print(news.target_names)"
   ],
   "id": "f1d8233d8315dc4a",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "18846\n",
      "From: Mamatha Devineni Ratnam <mr47+@andrew.cmu.edu>\n",
      "Subject: Pens fans reactions\n",
      "Organization: Post Office, Carnegie Mellon, Pittsburgh, PA\n",
      "Lines: 12\n",
      "NNTP-Posting-Host: po4.andrew.cmu.edu\n",
      "\n",
      "\n",
      "\n",
      "I am sure some bashers of Pens fans are pretty confused about the lack\n",
      "of any kind of posts about the recent Pens massacre of the Devils. Actually,\n",
      "I am  bit puzzled too and a bit relieved. However, I am going to put an end\n",
      "to non-PIttsburghers' relief with a bit of praise for the Pens. Man, they\n",
      "are killing those Devils worse than I thought. Jagr just showed you why\n",
      "he is much better than his regular season stats. He is also a lot\n",
      "fo fun to watch in the playoffs. Bowman should let JAgr have a lot of\n",
      "fun in the next couple of games since the Pens are going to beat the pulp out of Jersey anyway. I was very disappointed not to see the Islanders lose the final\n",
      "regular season game.          PENS RULE!!!\n",
      "\n",
      "\n",
      "[10  3 17  3  4]\n",
      "[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]\n",
      "['alt.atheism', 'comp.graphics', 'comp.os.ms-windows.misc', 'comp.sys.ibm.pc.hardware', 'comp.sys.mac.hardware', 'comp.windows.x', 'misc.forsale', 'rec.autos', 'rec.motorcycles', 'rec.sport.baseball', 'rec.sport.hockey', 'sci.crypt', 'sci.electronics', 'sci.med', 'sci.space', 'soc.religion.christian', 'talk.politics.guns', 'talk.politics.mideast', 'talk.politics.misc', 'talk.religion.misc']\n"
     ]
    }
   ],
   "execution_count": 14
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:16:00.164667Z",
     "start_time": "2025-01-10T11:15:58.266708Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 进行数据分割\n",
    "x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.25, random_state=1)\n",
    "\n",
    "# 对数据集进行特征抽取\n",
    "tf = TfidfVectorizer()\n",
    "\n",
    "# 以训练集当中的词的列表进行每篇文章重要性统计['a','b','c','d']\n",
    "x_train = tf.fit_transform(x_train)\n",
    "\n",
    "#针对特征内容，可以自行打印，下面的打印可以得到特征数目，总计有15万特征\n",
    "print(len(tf.get_feature_names_out()))"
   ],
   "id": "e427fc7f71de85a4",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "153196\n"
     ]
    }
   ],
   "execution_count": 15
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:19:20.427469Z",
     "start_time": "2025-01-10T11:19:19.827318Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 进行朴素贝叶斯算法的预测,alpha是拉普拉斯平滑系数，分子和分母加上一个系数，分母加alpha*特征词数目\n",
    "mlt = MultinomialNB(alpha=1.0)\n",
    "\n",
    "#训练模型\n",
    "mlt.fit(x_train, y_train)\n",
    "\n",
    "#特征数目不发生改变\n",
    "x_transform_test = tf.transform(x_test)\n",
    "x_transform_test.shape\n",
    "\n",
    "#预测模型\n",
    "y_predict = mlt.predict(x_transform_test)"
   ],
   "id": "69806697d4383fe5",
   "outputs": [],
   "execution_count": 17
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:19:21.932880Z",
     "start_time": "2025-01-10T11:19:21.910957Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 得出准确率\n",
    "print(\"准确率为：\", mlt.score(x_transform_test, y_test))\n",
    "\n",
    "# 打印分类报告\n",
    "# report():打印分类报告，target_names是标签的名字\n",
    "# precision, recall, f1-score, support是指标\n",
    "print(classification_report(y_test, y_predict, target_names=news.target_names))"
   ],
   "id": "aa8412d61a3b6406",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "准确率为： 0.8518675721561969\n",
      "                          precision    recall  f1-score   support\n",
      "\n",
      "             alt.atheism       0.91      0.77      0.83       199\n",
      "           comp.graphics       0.83      0.79      0.81       242\n",
      " comp.os.ms-windows.misc       0.89      0.83      0.86       263\n",
      "comp.sys.ibm.pc.hardware       0.80      0.83      0.81       262\n",
      "   comp.sys.mac.hardware       0.90      0.88      0.89       234\n",
      "          comp.windows.x       0.92      0.85      0.88       230\n",
      "            misc.forsale       0.96      0.67      0.79       257\n",
      "               rec.autos       0.90      0.87      0.88       265\n",
      "         rec.motorcycles       0.90      0.95      0.92       251\n",
      "      rec.sport.baseball       0.89      0.96      0.93       226\n",
      "        rec.sport.hockey       0.95      0.98      0.96       262\n",
      "               sci.crypt       0.76      0.97      0.85       257\n",
      "         sci.electronics       0.84      0.80      0.82       229\n",
      "                 sci.med       0.97      0.86      0.91       249\n",
      "               sci.space       0.92      0.96      0.94       256\n",
      "  soc.religion.christian       0.55      0.98      0.70       243\n",
      "      talk.politics.guns       0.76      0.96      0.85       234\n",
      "   talk.politics.mideast       0.93      0.99      0.96       224\n",
      "      talk.politics.misc       0.98      0.56      0.72       197\n",
      "      talk.religion.misc       0.97      0.26      0.41       132\n",
      "\n",
      "                accuracy                           0.85      4712\n",
      "               macro avg       0.88      0.84      0.84      4712\n",
      "            weighted avg       0.87      0.85      0.85      4712\n",
      "\n"
     ]
    }
   ],
   "execution_count": 18
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:22:22.574148Z",
     "start_time": "2025-01-10T11:22:22.570640Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 手动计算指标\n",
    "# 计算TP,FP,FN,TN\n",
    "\n",
    "# label为0的样本数\n",
    "# 测试集中，标签为0的样本数\n",
    "y_test1 = np.where(y_test == 0, 1, 0)\n",
    "print(y_test1.sum())\n",
    "\n",
    "# 预测结果中，标签为0的样本数\n",
    "y_predict1 = np.where(y_predict == 0, 1, 0)\n",
    "print(y_predict1.sum())\n",
    "\n",
    "print(\"TP:\", (y_test1 * y_predict1).sum())"
   ],
   "id": "a531a12352dd690e",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "199\n",
      "168\n",
      "TP: 153\n"
     ]
    }
   ],
   "execution_count": 20
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:23:35.951140Z",
     "start_time": "2025-01-10T11:23:35.945502Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 把0-19总计20个分类，变为0和1\n",
    "# 5是可以改为0到19的\n",
    "y_test1 = np.where(y_test == 5, 1, 0)\n",
    "# label为5的样本数\n",
    "print(y_test1.sum())\n",
    "\n",
    "y_predict1 = np.where(y_predict == 5, 1, 0)\n",
    "print(y_predict1.sum())\n",
    "\n",
    "# roc_auc_score的y_test只能是二分类,针对多分类计算AUC\n",
    "# AUC,Area Under the Curve,曲线下面积，是二分类的指标，AUC越大，分类效果越好\n",
    "# 多分类的AUC，可以用其他指标，比如F1-score,precision,recall,召回率等\n",
    "print(\"AUC指标：\", roc_auc_score(y_test1, y_predict1))"
   ],
   "id": "10e3664f5e0ed770",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "230\n",
      "214\n",
      "AUC指标： 0.924078924393225\n"
     ]
    }
   ],
   "execution_count": 21
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:26:11.681399Z",
     "start_time": "2025-01-10T11:26:11.675297Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#算多分类的精确率，召回率，F1-score\n",
    "\n",
    "# 计算TP,FP,FN,TN\n",
    "FP = np.where((np.array(y_test1) - np.array(y_predict1)) == -1, 1, 0).sum()\n",
    "TP = y_predict1.sum() - FP\n",
    "print(\"TP:\", TP)\n",
    "FN = np.where((np.array(y_test1) - np.array(y_predict1)) == 1, 1, 0).sum()\n",
    "print(\"FN:\", FN)\n",
    "TN = np.where(y_test1 == 0, 1, 0).sum() - FP  #4464\n",
    "print(\"TN:\", TN)\n",
    "\n",
    "#精确率\n",
    "precision = TP / (TP + FP)\n",
    "print(\"精确率:\", precision)\n",
    "\n",
    "#召回率\n",
    "recall = TP / (TP + FN)\n",
    "print(\"召回率:\", recall)\n",
    "\n",
    "#F1-score\n",
    "F1_score = 2 * precision * recall / (precision + recall)\n",
    "print(\"F1-score:\", F1_score)"
   ],
   "id": "7929cd12a5d3baa0",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TP: 196\n",
      "FN: 34\n",
      "TN: 4464\n",
      "精确率: 0.9158878504672897\n",
      "召回率: 0.8521739130434782\n",
      "F1-score: 0.8828828828828829\n"
     ]
    }
   ],
   "execution_count": 22
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": [
    "# 释放内存\n",
    "del news\n",
    "del x_train\n",
    "del x_test\n",
    "del y_test\n",
    "del y_predict\n",
    "del tf"
   ],
   "id": "9a2f15520c38f883"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 决策树",
   "id": "cbd7d1619062252"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:26:47.261548Z",
     "start_time": "2025-01-10T11:26:47.258382Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from sklearn.model_selection import train_test_split, GridSearchCV\n",
    "from sklearn.feature_extraction import DictVectorizer\n",
    "from sklearn.tree import DecisionTreeClassifier, export_graphviz\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "import pandas as pd\n",
    "import numpy as np"
   ],
   "id": "c7eede5635db0daa",
   "outputs": [],
   "execution_count": 23
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:37:08.188521Z",
     "start_time": "2025-01-10T11:37:08.176149Z"
    }
   },
   "cell_type": "code",
   "source": [
    "\"\"\"\n",
    "决策树对泰坦尼克号进行预测生死\n",
    ":return: None\n",
    "\"\"\"\n",
    "# 获取数据\n",
    "titan = pd.read_csv(\"./data/titanic.txt\")\n",
    "\n",
    "# 处理数据，找出特征值和目标值\n",
    "x = titan[['pclass', 'age', 'sex']]\n",
    "y = titan['survived']\n",
    "\n",
    "# 用来判断是否有空值\n",
    "print(x.info())\n",
    "x.describe(include='all')"
   ],
   "id": "4e63c8382e108e28",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 1313 entries, 0 to 1312\n",
      "Data columns (total 3 columns):\n",
      " #   Column  Non-Null Count  Dtype  \n",
      "---  ------  --------------  -----  \n",
      " 0   pclass  1313 non-null   object \n",
      " 1   age     633 non-null    float64\n",
      " 2   sex     1313 non-null   object \n",
      "dtypes: float64(1), object(2)\n",
      "memory usage: 30.9+ KB\n",
      "None\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "       pclass         age   sex\n",
       "count    1313  633.000000  1313\n",
       "unique      3         NaN     2\n",
       "top       3rd         NaN  male\n",
       "freq      711         NaN   850\n",
       "mean      NaN   31.194181   NaN\n",
       "std       NaN   14.747525   NaN\n",
       "min       NaN    0.166700   NaN\n",
       "25%       NaN   21.000000   NaN\n",
       "50%       NaN   30.000000   NaN\n",
       "75%       NaN   41.000000   NaN\n",
       "max       NaN   71.000000   NaN"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>pclass</th>\n",
       "      <th>age</th>\n",
       "      <th>sex</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>1313</td>\n",
       "      <td>633.000000</td>\n",
       "      <td>1313</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>unique</th>\n",
       "      <td>3</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>top</th>\n",
       "      <td>3rd</td>\n",
       "      <td>NaN</td>\n",
       "      <td>male</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>freq</th>\n",
       "      <td>711</td>\n",
       "      <td>NaN</td>\n",
       "      <td>850</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>NaN</td>\n",
       "      <td>31.194181</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>NaN</td>\n",
       "      <td>14.747525</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>NaN</td>\n",
       "      <td>0.166700</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>NaN</td>\n",
       "      <td>21.000000</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>NaN</td>\n",
       "      <td>30.000000</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>NaN</td>\n",
       "      <td>41.000000</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>NaN</td>\n",
       "      <td>71.000000</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 26
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:37:58.043208Z",
     "start_time": "2025-01-10T11:37:58.037335Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 对缺失值进行处理,填为均值\n",
    "mean = x['age'].mean()\n",
    "x.loc[:, 'age'] = x.loc[:, 'age'].fillna(mean)\n",
    "x.info()"
   ],
   "id": "8c5b9495c4bf8df6",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 1313 entries, 0 to 1312\n",
      "Data columns (total 3 columns):\n",
      " #   Column  Non-Null Count  Dtype  \n",
      "---  ------  --------------  -----  \n",
      " 0   pclass  1313 non-null   object \n",
      " 1   age     1313 non-null   float64\n",
      " 2   sex     1313 non-null   object \n",
      "dtypes: float64(1), object(2)\n",
      "memory usage: 30.9+ KB\n"
     ]
    }
   ],
   "execution_count": 27
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:42:59.243716Z",
     "start_time": "2025-01-10T11:42:59.239168Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 分割数据集到训练集合测试集\n",
    "x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25, random_state=4)"
   ],
   "id": "b1bc937be87ab185",
   "outputs": [],
   "execution_count": 35
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:42:59.886320Z",
     "start_time": "2025-01-10T11:42:59.879724Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#性别是女性的数量\n",
    "x_train[x_train['sex'] == 'female'].count()\n",
    "\n",
    "#z是为了把特征和目标存储到一起\n",
    "z = x_train.copy()\n",
    "\n",
    "#把目标值存储到z中\n",
    "z['survived'] = y_train\n",
    "\n",
    "#女性中存活的情况对比\n",
    "#男性中存活的情况\n",
    "z[z['sex'] == 'female']['survived'].value_counts()\n",
    "z[z['sex'] == 'male']['survived'].value_counts()"
   ],
   "id": "a5fa539108a3d0c9",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "survived\n",
       "0    539\n",
       "1    104\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 36
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:43:00.476197Z",
     "start_time": "2025-01-10T11:43:00.467680Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#把df变为字典，样本变为一个一个的字典，字典中列名变为键\n",
    "x_train.to_dict(orient=\"records\")\n",
    "\n",
    "# 进行处理（特征工程）特征-》类别-》one_hot编码\n",
    "dict = DictVectorizer(sparse=False)\n",
    "\n",
    "# 这一步是对字典进行特征抽取,to_dict可以把df变为字典，records代表列名变为键\n",
    "x_train = dict.fit_transform(x_train.to_dict(orient=\"records\"))\n",
    "print(type(x_train))\n",
    "print(dict.get_feature_names_out())\n",
    "print('-' * 50)\n",
    "x_test = dict.transform(x_test.to_dict(orient=\"records\"))\n",
    "print(x_train)"
   ],
   "id": "bde302108ce74524",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'>\n",
      "['age' 'pclass=1st' 'pclass=2nd' 'pclass=3rd' 'sex=female' 'sex=male']\n",
      "--------------------------------------------------\n",
      "[[30.          0.          1.          0.          0.          1.        ]\n",
      " [62.          1.          0.          0.          0.          1.        ]\n",
      " [31.19418104  0.          0.          1.          1.          0.        ]\n",
      " ...\n",
      " [34.          0.          1.          0.          0.          1.        ]\n",
      " [46.          1.          0.          0.          0.          1.        ]\n",
      " [31.19418104  0.          0.          1.          0.          1.        ]]\n"
     ]
    }
   ],
   "execution_count": 37
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T11:43:11.622218Z",
     "start_time": "2025-01-10T11:43:11.608148Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 用决策树进行预测，修改max_depth试试,修改criterion为entropy\n",
    "#树过于复杂，就会产生过拟合\n",
    "dec = DecisionTreeClassifier()\n",
    "\n",
    "#训练\n",
    "dec.fit(x_train, y_train)\n",
    "\n",
    "# 预测准确率\n",
    "print(\"预测的准确率：\", dec.score(x_test, y_test))\n",
    "\n",
    "# 导出决策树的结构\n",
    "export_graphviz(dec, out_file=\"tree.dot\",\n",
    "                feature_names=['age', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', 'female', 'male'])\n"
   ],
   "id": "4c449829478a28ae",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预测的准确率： 0.8085106382978723\n"
     ]
    }
   ],
   "execution_count": 38
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "32d61c1e9c56fb18"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
